/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package service.reportCenter.posReports;

import com.openbrew.openbrewrf.POSLineItems;
import com.openbrew.openbrewrf.POSProductServingType;
import com.openbrew.openbrewrf.POSSale;
import com.openbrew.openbrewrf.POSSetup;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 *
 * @author chapmand
 */
@Stateless
@Path("com.openbrew.openbrewrf.posdetailedreport")
public class POSDetailedReportREST {
    @PersistenceContext(unitName = "com.openBrew_openBrewRF_war_1.0PU")
    private EntityManager em;
    
    public POSDetailedReportREST() {
    }
    
    private List<POSSale> sales = new ArrayList<POSSale>();
    private POSSetup setup = null;
    
    private void loadSales(final Date startDate, final Date stopDate){
        sales.removeAll(sales);
        TypedQuery<POSSale> query = em.createQuery(
                "SELECT s FROM POSSale s WHERE s.tabOpenTime >= ?1 AND s.tabOpenTime <= ?2"
                , POSSale.class);
        query.setParameter(1, startDate, TemporalType.TIMESTAMP);
        query.setParameter(2, stopDate, TemporalType.TIMESTAMP);
        sales = query.getResultList();
    }
    
    private void loadSetup(){
        TypedQuery<POSSetup> setupQuery = em.createQuery(
                "SELECT s FROM POSSetup s WHERE s.id = '1'", POSSetup.class);
        setup = setupQuery.getSingleResult();
    }
    
    private float getPrice(POSLineItems item){
        if(item.getPriceOverRide()>0){
            return item.getPriceOverRide();
        }
        if(item.getProduct()!=null){
            float cost = item.getProduct().getStCost();
            if(item.getDiscount()!=null){
                if(item.getDiscount().getFlat()>0){
                    cost = cost - item.getDiscount().getFlat();
                } else if(item.getDiscount().getPct()>0){
                    cost = cost - (cost * item.getDiscount().getPct());
                }
            }
            return cost;
        }
        if(item.getSupply()!=null){
            float cost = item.getSupply().getSupReSalePrice();
            if(item.getDiscount()!=null){
                if(item.getDiscount().getFlat()>0){
                    cost = cost - item.getDiscount().getFlat();
                } else if(item.getDiscount().getPct()>0){
                    cost = cost - (cost * item.getDiscount().getPct());
                }
            }
            return cost;
        }
        return 0;
    }
    
    @GET
    @Path("{startDate}/{stopDate}")
    @Produces(MediaType.APPLICATION_XML)
    public List<DetReport> find(@PathParam("startDate") Date startDate
            , @PathParam("stopDate") Date stopDate) {
        //Set Dates
        Calendar calStart = Calendar.getInstance();
        calStart.setTime(startDate);
        calStart.set(Calendar.HOUR_OF_DAY, 0);
        calStart.set(Calendar.MINUTE, 0);
        calStart.set(Calendar.SECOND, 0);
        final Date calStartDate = calStart.getTime();
        Calendar calFin = Calendar.getInstance();
        calFin.setTime(stopDate);
        calFin.set(Calendar.HOUR_OF_DAY, 23);
        calFin.set(Calendar.MINUTE, 59);
        calFin.set(Calendar.SECOND, 59);
        final Date calFinDate = calFin.getTime();
        
        //Load all sales between said dates.
        loadSales(calStartDate, calFinDate);
        loadSetup();
        
        //Parse Salse into appropriate class.
        List<DetReport> report = createReport(calStartDate, calFinDate);
        
        for(final POSSale sale : sales){
            Calendar cal = Calendar.getInstance();
            cal.setTime(sale.getTabOpenTime());
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            final Date calTempDate = cal.getTime();
            for(final DetReport dt: report){
                if(dt.getDate().equals(calTempDate)){
                    //Sale date is equal to report date.
                    //First append sales info.
                    dt.setCash(dt.getCash() + sale.getSaleCash());
                    dt.setCredit(dt.getCredit() + sale.getSaleCredit());
                    dt.setGiftCard(dt.getGiftCard() + sale.getSaleGiftCard());
                    dt.setTab(dt.getTab() + sale.getSaleOther());
                    
                    //Now set up all beer sales.
                    if(sale.getLineItemTypeCollection()!=null){
                        for(final POSLineItems item : sale.getLineItemTypeCollection()){
                            //Check if it is a beer, if so, add it to the array.
                            if(item.getProduct()!=null){
                                if(dt.getBeers() != null){
                                    boolean found = false;
                                    for(final DetReportBeer drb : dt.getBeers()){
                                        if(item.getProduct().getGlassware() != null 
                                                && item.getProduct().getServingTypeBeer() != null
                                                && drb.getBeer() != null
                                                && drb.getGlassware() != null){
                                            if((drb.getBeer().getbId() == item.getProduct().getServingTypeBeer().getbId())
                                                    && (drb.getGlassware().getId() == item.getProduct().getGlassware().getId())){
                                                found = true;
                                                drb.setQty(drb.getQty() + item.getQty());
                                                drb.setCost(drb.getCost() + getPrice(item));
                                            }
                                        }
                                    }
                                    if(!found){
                                        DetReportBeer drb = new DetReportBeer();
                                        drb.setBeer(item.getProduct().getServingTypeBeer());
                                        drb.setGlassware(item.getProduct().getGlassware());
                                        drb.setQty(item.getQty());
                                        drb.setCost(getPrice(item));
                                        dt.getBeers().add(drb);
                                    }
                                } else {
                                    DetReportBeer drb = new DetReportBeer();
                                    drb.setBeer(item.getProduct().getServingTypeBeer());
                                    drb.setGlassware(item.getProduct().getGlassware());
                                    drb.setQty(item.getQty());
                                    drb.setCost(getPrice(item));
                                    List<DetReportBeer> drbs = new ArrayList<DetReportBeer>();
                                    drbs.add(drb);
                                    dt.setBeers(drbs);
                                }
                            }
                            //Check if it is a Supply, if so, add it to the array.
                            if(item.getSupply()!=null){
                                if(dt.getSupplies() != null){
                                    boolean found = false;
                                    for(final DetReportSupplies drs : dt.getSupplies()){
                                        if(drs.getSupply().getSupID() == item.getSupply().getSupID()){
                                            found = true;
                                            drs.setQty(drs.getQty() + item.getQty());
                                            drs.setCost(drs.getCost() + getPrice(item));
                                        }
                                    }
                                    if(!found){
                                        DetReportSupplies drs = new DetReportSupplies();
                                        drs.setSupply(item.getSupply());
                                        drs.setQty(item.getQty());
                                        drs.setCost(getPrice(item));
                                        dt.getSupplies().add(drs);
                                    }
                                } else {
                                    DetReportSupplies drs = new DetReportSupplies();
                                    drs.setSupply(item.getSupply());
                                    drs.setQty(item.getQty());
                                    drs.setCost(getPrice(item));
                                    List<DetReportSupplies> drss = new ArrayList<DetReportSupplies>();
                                    drss.add(drs);
                                    dt.setSupplies(drss);
                                }
                            }
                            //Check if it is a Taster Tray, if so, add it to the array.
                            if(item.getTasterTray()!=null){
                                for(POSProductServingType taster : item.getTasterTray().getServingTypeCollection()){
                                    if(dt.getBeers() != null){
                                        boolean found = false;
                                        for(final DetReportBeer drb : dt.getBeers()){
                                            if(taster.getGlassware() != null
                                                    && taster.getServingTypeBeer() != null
                                                    && drb.getBeer() != null
                                                    && drb.getGlassware() != null){
                                                if((drb.getBeer().getbId() == taster.getServingTypeBeer().getbId())
                                                        && (drb.getGlassware().getId() == taster.getGlassware().getId())){
                                                    found = true;
                                                    drb.setQty(drb.getQty() + item.getQty());
                                                    drb.setCost(drb.getCost() + (taster.getStCost()-setup.getTasterDiscount()));
                                                }
                                            }
                                        }
                                        if(!found){
                                            DetReportBeer drb = new DetReportBeer();
                                            drb.setBeer(taster.getServingTypeBeer());
                                            drb.setGlassware(taster.getGlassware());
                                            drb.setQty(item.getQty());
                                            drb.setCost(taster.getStCost()-setup.getTasterDiscount());
                                            dt.getBeers().add(drb);
                                        }
                                    } else {
                                        DetReportBeer drb = new DetReportBeer();
                                        drb.setBeer(taster.getServingTypeBeer());
                                        drb.setGlassware(taster.getGlassware());
                                        drb.setQty(item.getQty());
                                        drb.setCost(taster.getStCost()-setup.getTasterDiscount());
                                        List<DetReportBeer> drbs = new ArrayList<DetReportBeer>();
                                        drbs.add(drb);
                                        dt.setBeers(drbs);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        
        return report;
    }
    
    private List<DetReport> createReport(Date startDate, Date stopDate){
        List<DetReport> report = new ArrayList<DetReport>();
        
        //Create a DetReport for each date.
        while(startDate.before(stopDate)){
            DetReport rep = new DetReport();
            rep.setDate(startDate);
            Calendar cal = Calendar.getInstance();
            cal.setTime(startDate);
            cal.add(Calendar.DATE, 1);
            startDate = cal.getTime();
            report.add(rep);
        }
        
        return report;
    }
    
    protected EntityManager getEntityManager() {
        return em;
    }
}
